﻿using System.Reflection;
using Devonline.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.OData.Edm;
using Microsoft.OData.ModelBuilder;

namespace Devonline.AspNetCore.OData;

public static class ODataExtensions
{
    /// <summary>
    /// 按照默认的命名约定, 从数据库上下文中注册的实体类型名字中注册 odata 实体类型
    /// </summary>
    /// <typeparam name="TDbContext">数据库上下文实例类型</typeparam>
    /// <param name="builder">ODataModelBuilder 实例</param>
    /// <returns></returns>
    public static ODataModelBuilder GetEdmModels<TDbContext>(this ODataModelBuilder builder) where TDbContext : DbContext
    {
        var entitySets = typeof(TDbContext).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.IsCollectible && x.PropertyType.IsGenericType && x.PropertyType == typeof(DbSet<>));

        //builder.EntitySet<Item>(nameof(ApplicationDbContext.Items));
        //builder.EntityType<Item>().CollectionProperty(x => x.Additionals).IsNavigable();
        foreach (var entitySet in entitySets)
        {
            builder.InvokeGenericMethod(nameof(builder.EntitySet), new object[] { entitySet.Name }, out object? returnValue, entitySet.PropertyType.GetGenericArguments());
        }

        return builder;
    }

    /// <summary>
    /// 构建 EdmModel 模型, 如果是使用 ODataConventionModelBuilder 则根据 camelCase 设置是否使用驼峰法字段名
    /// </summary>
    /// <param name="builder">ODataModelBuilder 实例</param>
    /// <param name="camelCase">是否使用驼峰法命名</param>
    /// <returns></returns>
    public static IEdmModel BuildEdmModel(this ODataModelBuilder builder, bool camelCase = true)
    {
        if (camelCase && builder is ODataConventionModelBuilder odataBuilder)
        {
            builder = odataBuilder.EnableLowerCamelCase();
        }

        return builder.GetEdmModel();
    }
}